﻿#pragma once
#include "OpenGL项目主标头.h"
#include "OpenGL缓冲区类标头.h" // 包含头文件，include 的相对路径就是当前文件所在路径
// C/C++ 标准库学习网站：https://legacy.cplusplus.com
// C/C++ 微软(Visual Studio)中文学习网站：https://learn.microsoft.com/zh-cn/cpp/cpp/?view=msvc-170
// OpenGl 学习网站：https://www.khronos.org/opengl/wiki
// OpenGl 的 GLFW 学习网站：https://www.glfw.org/docs/latest/glfw3_8h.html#ac06b663d79c8fcf04669cc8fcc0b7670
// OpenGl 的 GLEW 学习网站：https://docs.gl/

// 顶点缓冲区类 VertexBuffer
VertexBuffer::VertexBuffer(const void* data, unsigned int size, uint32_t id)
    : m_id(id) {
    gl_call(glGenBuffers(m_id, &m_vertex_renderer_id)); // 生成 VBO 缓冲
    cout << "VBO ID: " << m_vertex_renderer_id << endl; // 打印 VBO ID（索引缓冲区的 ID）
    gl_call(glBindBuffer(GL_ARRAY_BUFFER, m_vertex_renderer_id)); // 绑定 VBO 缓冲
    gl_call(glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW));  // 写入数据
}

VertexBuffer::~VertexBuffer() {
    printf("deleted vertex buffer %ud\n", m_vertex_renderer_id);
    gl_call(glDeleteBuffers(m_id, &m_vertex_renderer_id)); // 删除 VBO 缓冲
}

void VertexBuffer::bind() const {
    gl_call(glBindBuffer(GL_ARRAY_BUFFER, m_vertex_renderer_id)); // 绑定 VBO 缓冲
}

void VertexBuffer::unbind() const {
    gl_call(glBindBuffer(GL_ARRAY_BUFFER, 0)); // 解除绑定 VBO 缓冲
}


// 索引缓冲区类 IndexBuffer
IndexBuffer::IndexBuffer(const unsigned int* data, unsigned int count, uint32_t id)
    : m_id(id), m_index_count(count) {
    gl_assert(sizeof(unsigned int) == sizeof(GLuint));
    //unsigned int vertex_buffer; // 可以去头文件中查看宏 glGenBuffers 的参数格式
    gl_call(glGenBuffers(m_id, &m_index_renderer_id)); // 生成 EBO 缓冲
    cout << "EBO ID: " << m_index_renderer_id << endl; // 打印 EBO ID（索引缓冲区的 ID）
    gl_call(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_renderer_id)); // 绑定 EBO 缓冲
    gl_call(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), data, GL_STATIC_DRAW));  // 写入数据
}

IndexBuffer::~IndexBuffer() {
    printf("deleted index buffer %ud\n", m_index_renderer_id);
    gl_call(glDeleteBuffers(m_id, &m_index_renderer_id)); // 删除 EBO 缓冲
}

void IndexBuffer::bind() const {
    gl_call(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_renderer_id)); // 绑定 EBO 缓冲
}

void IndexBuffer::unbind() const {
    gl_call(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); // 解除绑定 EBO 缓冲
}


// 顶点数组类 VertexArray
VertexArray::VertexArray(unsigned int id)
    : m_id(id) {
    gl_call(glGenVertexArrays(m_id, &m_vertex_array_renderer_id)); // 生成指定 ID 的顶点数组 VAO 对象
    cout << "VAO ID: " << m_vertex_array_renderer_id << endl; // 打印 VAO ID
}

VertexArray::~VertexArray() {
    printf("deleted vertex array %d\n", m_vertex_array_renderer_id);
    gl_call(glDeleteVertexArrays(m_id, &m_vertex_array_renderer_id)); // 删除顶点数组 VAO 对象
}

void VertexArray::bind() const {
    gl_call(glBindVertexArray(m_vertex_array_renderer_id)); // 绑定顶点数组 VAO 对象
}

void VertexArray::unbind() const {
    gl_call(glBindVertexArray(0)); // 解除绑定顶点数组 VAO 对象
}

void VertexArray::add_buffer(const VertexBuffer& vb, const VertexBufferLayout& layout, unsigned int offset) {
    bind();     // 绑定顶点数组 VAO 对象
    vb.bind();  // 绑定 VBO 缓冲
    const auto& elements = layout.get_elements();
    for (unsigned int i = 0; i < elements.size(); ++i) {
        const auto& element = elements[i];
        gl_call(glEnableVertexAttribArray(i)); // 启用顶点属性
        gl_call(glVertexAttribPointer(i, element.count, element.type, element.normalized, layout.get_stride(), reinterpret_cast<const void*>(static_cast<size_t>(offset))));
        offset += element.count * VertexBufferElement::get_type_size(element.type); // 计算下一个顶点属性的偏移量
    }
}
